<script setup lang="ts">
// NOTE:
// 编译时：通过指定泛型来定义组件接受属性 modelValue必传且为布尔类型
// 运行时：还有一种方式就是直接传递值函数参数 { modelValue: { type: Boolean as PropType<boolean>, required: true } }
const props = defineProps<{
  modelValue: boolean
  appendToBody?: boolean
}>()

defineEmits(['update:modelValue'])

const isVisible = useVModel(props)

// 锁定 document.body 滚动
const isLocked = useScrollLock(document.body)

watch(isVisible, async (newVal) => {
  await nextTick()
  isLocked.value = newVal!
}, {
  immediate: true,
})
</script>

<template>
  <teleport to="body" :disabled="!appendToBody">
    <div class="popup">
      <!-- mask -->
      <transition name="fade">
        <div v-if="isVisible" class="mask w-screen h-screen bg-zinc-900/80 z-40 fixed top-0 left-0" @click="isVisible = false" />
      </transition>
      <!-- content -->
      <transition name="popup-down-up">
        <div v-if="isVisible" v-bind="$attrs" class="content w-screen bg-white z-50 fixed bottom-0">
          <slot />
        </div>
      </transition>
    </div>
  </teleport>
</template>

<style lang="scss" scoped>
.fade-enter-active, .fade-leave-active {
  transition: all 0.3s;
}

// 准备进入，离开完成
.fade-enter-from, .fade-enter-to {
  opacity: 0;
}

.popup-down-up-enter-active,
.popup-down-up-leave-active {
  transition: all 0.3s;
}

.popup-down-up-enter-from,
.popup-down-up-leave-to {
  transform: translateY(100%);
}
</style>
